/*
 * Copyright (c) 2020 HiHope Community.
 * Description: mq2 demo
 * Author: HiSpark Product Team.
 * Create: 2020-5-20
 */
#include <math.h>
#include <hi_early_debug.h>
#include <hi_task.h>
#include <hi_time.h>
#include <hi_adc.h>
#include <hi_stdlib.h>
#include <hi_watchdog.h>
#include <ssd1306_oled.h>
#include <hi_pwm.h>
#include <hi_io.h>
#include <hi_gpio.h>
#include <app_demo_hx711.h>

//Calibration parameters
//Because the characteristic curves of different sensors are not very consistent, each sensor needs to correct this parameter to make the measured value very accurate.
//When it is found that the measured weight is too large, increase the value.
//If the measured weight is small, reduce the modified value.
//The value can be decimal, and can be adjusted by 10 with reference to the error 1g
//#define GapValue 1300
#define GapValue_Cat 1482
#define GapValue_Dog 1300
double hx711_weight_cat;
double hx711_weight_dog;
unsigned long Sensor_Read_Cat(void);
double Get_Sensor_Read_Cat(void);
unsigned long Sensor_Read_Dog(void);
double Get_Sensor_Read_Dog(void);
hi_void gpio_init() {
	hi_io_set_func(HI_IO_NAME_GPIO_13, HI_IO_FUNC_GPIO_13_I2C0_SDA);
    hi_io_set_func(HI_IO_NAME_GPIO_14, HI_IO_FUNC_GPIO_14_I2C0_SCL);
}


hi_void *hi_hx711_cat(hi_void *param)
{	
	(void*)(param);

	gpio_init();
	//Initialize gpio11 as GPIO input and DT pin of sensor
    hi_io_set_func(HI_IO_NAME_GPIO_11, HI_IO_FUNC_GPIO_11_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_11,HI_GPIO_DIR_IN);
	//Initialize gpio11 as GPIO output and SCK pin of sensor
    hi_io_set_func(HI_IO_NAME_GPIO_12, HI_IO_FUNC_GPIO_12_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_12,HI_GPIO_DIR_OUT);
    hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,0);
	//Initialize I2C and use OLED screen
    hi_i2c_init(HI_I2C_IDX_0, HI_I2C_IDX_BAUDRATE); /* baudrate: 400kbps */
    hi_i2c_set_baudrate(HI_I2C_IDX_0, HI_I2C_IDX_BAUDRATE);
	//OLED initializes and displays the corresponding information
    while( HI_ERR_SUCCESS != oled_init()) ;
	oled_fill_screen(OLED_CLEAN_SCREEN);
    oled_show_str(0,1,"Cat Food: ",1);
	oled_show_str(0,5,"Dog Food: ",1);

    double base_data_cat = 0;
	hx711_weight_cat = 0;
	hi_u8 buf[10] = {0};
    base_data_cat = Get_Sensor_Read_Cat(); //Get benchmark value
	
     while (1)
     {
        hx711_weight_cat = (Get_Sensor_Read_Cat() - base_data_cat) / GapValue_Cat; //Gain weight of the cat food
        if(hx711_weight_cat > 0) // Display when greater than 0
        {
            printf("weight of cat food :   %.1f\r\n" ,hx711_weight_cat);  
            sprintf_s(buf,10,"%.1f g ",hx711_weight_cat);
            oled_show_str(20,3, buf,1);
        }else
		{
			hx711_weight_cat = -hx711_weight_cat;
			printf("weight of cat food :   %.1f\r\n" ,hx711_weight_cat);  
            sprintf_s(buf,10,"%.1f g ",hx711_weight_cat);
            oled_show_str(20,3, buf,1);
		}
        hi_sleep(1000);  
     }
}

hi_void *hi_hx711_dog(hi_void *param)
{	
	(void*)(param);
	
	gpio_init();
	//Initialize gpio6 as GPIO input and DT pin of sensor
    hi_io_set_func(HI_IO_NAME_GPIO_6, HI_IO_FUNC_GPIO_6_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_6,HI_GPIO_DIR_IN);
	//Initialize gpio8 as GPIO output and SCK pin of sensor
    hi_io_set_func(HI_IO_NAME_GPIO_8, HI_IO_FUNC_GPIO_8_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_8,HI_GPIO_DIR_OUT);
    hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_8,0);
	//Initialize I2C and use OLED screen
    // hi_i2c_init(HI_I2C_IDX_1, HI_I2C_IDX_BAUDRATE); /* baudrate: 400kbps */
    // hi_i2c_set_baudrate(HI_I2C_IDX_1, HI_I2C_IDX_BAUDRATE);

    double base_data_dog = 0;
	hx711_weight_dog = 0;
	hi_u8 buf[10] = {0};
    base_data_dog = Get_Sensor_Read_Dog(); //Get benchmark value
	
     while (1)
     {
        hx711_weight_dog = (Get_Sensor_Read_Dog() - base_data_dog) / GapValue_Dog; //Gain weight
        if(hx711_weight_dog > 0) // Display when greater than 0
        {
            printf("weight of dog food :   %.1f\r\n" ,hx711_weight_dog);  
            sprintf_s(buf,10,"%.1f g ",hx711_weight_dog);
            oled_show_str(20,7, buf,1);
        }else
		{
			hx711_weight_dog= -hx711_weight_dog;
			printf("weight of dog food :   %.1f\r\n" ,hx711_weight_dog);  
            sprintf_s(buf,10,"%.1f g ",hx711_weight_dog);
            oled_show_str(20,7, buf,1);
		}
        hi_sleep(1000);  
     }
}

#define HX711_TASK_STACK_SIZE_CAT	(4*1024)
#define HX711_MSG_TASK_PRIO_CAT	(27)
hi_u32 hx711_task_id_cat;

#define HX711_TASK_STACK_SIZE_DOG	(4*1024)
#define HX711_MSG_TASK_PRIO_DOG	(27)
hi_u32 hx711_task_id_dog;

hi_u32 hi_hx711_cat_task(hi_void)
{
    hi_u32 ret; 
    
    hi_task_attr hx711_attr;

	hx711_attr.stack_size = HX711_TASK_STACK_SIZE_CAT;
    hx711_attr.task_prio = HX711_MSG_TASK_PRIO_CAT;
    hx711_attr.task_name = (hi_char*)"hx711 cat task ";

    ret = hi_task_create(&hx711_task_id_cat, &hx711_attr, hi_hx711_cat, HI_NULL);
    if (ret != HI_ERR_SUCCESS) {
        printf("Failed to create hx711 cat task\r\n");
        return HI_ERR_FAILURE;
    }
    return HI_ERR_SUCCESS;
}

hi_u32 hi_hx711_dog_task(hi_void)
{
    hi_u32 ret; 
    
    hi_task_attr hx711_attr;

	hx711_attr.stack_size = HX711_TASK_STACK_SIZE_DOG;
    hx711_attr.task_prio = HX711_MSG_TASK_PRIO_DOG;
    hx711_attr.task_name = (hi_char*)"hx711 dog task";

    ret = hi_task_create(&hx711_task_id_dog, &hx711_attr, hi_hx711_dog, HI_NULL);
    if (ret != HI_ERR_SUCCESS) {
        printf("Failed to create hx711 dog task\r\n");
        return HI_ERR_FAILURE;
    }
    return HI_ERR_SUCCESS;
}


unsigned long Sensor_Read_Cat(void)
{
	unsigned long value = 0;
	unsigned char i = 0;
	hi_gpio_value input = 0;
	hi_udelay(2);
	//When the clock line is pulled down and idle, the clock line keeps low potential
	hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,0);
	hi_udelay(2);	
	hi_gpio_get_input_val(HI_IO_NAME_GPIO_11,&input);
	//Wait for AD conversion to finish
	while(input)
    {
        hi_gpio_get_input_val(HI_IO_NAME_GPIO_11,&input);
    }
	for(i=0;i<24;i++)
	{
		//The clock line is pulled up to send the clock pulse
		hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,1);
		// hi_udelay(2);
		
		//Shift left and fill zero right to wait for receiving data
		value = value << 1;
		//Clock line down
		hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,0);
		// hi_udelay(2);
		//Read one bit data
        hi_gpio_get_input_val(HI_IO_NAME_GPIO_11,&input);
		if(input){
			value ++;
        }
		
	}
	//The 25th pulse
	hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,1);
	hi_udelay(2);
	value = value^0x800000;	
	//25th pulse end
	hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_12,0);	
	hi_udelay(2);	
	return value;
}
unsigned long Sensor_Read_Dog(void)
{
	unsigned long value = 0;
	unsigned char i = 0;
	hi_gpio_value input = 0;
	hi_udelay(2);
	//When the clock line is pulled down and idle, the clock line keeps low potential
	hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_8,0);
	hi_udelay(2);	
	hi_gpio_get_input_val(HI_IO_NAME_GPIO_6,&input);
	//Wait for AD conversion to finish
	while(input)
    {
        hi_gpio_get_input_val(HI_IO_NAME_GPIO_6,&input);
    }
	for(i=0;i<24;i++)
	{
		//The clock line is pulled up to send the clock pulse
		hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_8,1);
		// hi_udelay(2);
		
		//Shift left and fill zero right to wait for receiving data
		value = value << 1;
		//Clock line down
		hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_8,0);
		// hi_udelay(2);
		//Read one bit data
        hi_gpio_get_input_val(HI_IO_NAME_GPIO_6,&input);
		if(input){
			value ++;
        }
		
	}
	//The 25th pulse
	hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_8,1);
	hi_udelay(2);
	value = value^0x800000;	
	//25th pulse end
	hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_8,0);	
	hi_udelay(2);	
	return value;
}
/*get serson data*/ 
double Get_Sensor_Read_Cat(void)
{
  	double sum = 0;    // In order to reduce the error, take out 10 values at a time and calculate the average value.
  	for (int i = 0; i < 10; i++) // The more loops, the higher the accuracy, and of course, the more time it takes
    	sum += Sensor_Read_Cat();  // accumulation
  	return (sum/10); // Calculate the average value for average difference

}

/*get serson data*/ 
double Get_Sensor_Read_Dog(void)
{
  	double sum = 0;    // In order to reduce the error, take out 10 values at a time and calculate the average value.
  	for (int i = 0; i < 10; i++) // The more loops, the higher the accuracy, and of course, the more time it takes
    	sum += Sensor_Read_Dog();  // accumulation
  	return (sum/10); // Calculate the average value for average difference

}
